implement extended layout for GtkTreeView and GtkTreeViewColumn
authorMatthias Clasen <mclasen@redhat.com>
Sat, 19 Dec 2009 07:07:51 +0000 (02:07 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 19 Dec 2009 07:07:51 +0000 (02:07 -0500)
gtk/gtktreeprivate.h
gtk/gtktreeview.c
gtk/gtktreeviewcolumn.c
gtk/gtktreeviewcolumn.h

index dd0cf8d2a9bef7d7f22cb36277d6e73d85e88607..43c6e31069a26573b50e42b3878a6c60a9a96209 100644 (file)
@@ -77,6 +77,8 @@ enum
   */
 #define TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER(tree_view) (10*TREE_VIEW_HEADER_HEIGHT(tree_view))
 
+#define GTK_TREE_VIEW_COLUMN_GET_PRIVATE(column) (G_TYPE_INSTANCE_GET_PRIVATE ((column), GTK_TYPE_TREE_VIEW_COLUMN, GtkTreeViewColumnPrivate))
+
 typedef struct _GtkTreeViewColumnReorder GtkTreeViewColumnReorder;
 struct _GtkTreeViewColumnReorder
 {
@@ -298,6 +300,11 @@ struct _GtkTreeViewPrivate
   guint search_entry_avoid_unhandled_binding : 1;
 };
 
+struct _GtkTreeViewColumnPrivate
+{
+  gint natural_width;
+};
+
 #ifdef __GNUC__
 
 #define TREE_VIEW_INTERNAL_ASSERT(expr, ret)     G_STMT_START{          \
index 47b8e59d8103bf2323d1ba72ecc1b9fee6e85af0..53732cd65c17c9997cd24d3930228650d0dd05e1 100644 (file)
@@ -27,6 +27,7 @@
 #include "gtktreednd.h"
 #include "gtktreeprivate.h"
 #include "gtkcellrenderer.h"
+#include "gtkextendedlayout.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkbuildable.h"
@@ -469,7 +470,7 @@ static void gtk_tree_view_buildable_add_child (GtkBuildable *tree_view,
                                               GObject     *child,
                                               const gchar *type);
 static void gtk_tree_view_buildable_init      (GtkBuildableIface *iface);
-
+static void gtk_tree_view_extended_layout_init (GtkExtendedLayoutIface *iface);
 
 static gboolean scroll_row_timeout                   (gpointer     data);
 static void     add_scroll_timeout                   (GtkTreeView *tree_view);
@@ -484,7 +485,10 @@ static guint tree_view_signals [LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-                                               gtk_tree_view_buildable_init))
+                                               gtk_tree_view_buildable_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+                                                gtk_tree_view_extended_layout_init))
+
 
 static void
 gtk_tree_view_class_init (GtkTreeViewClass *class)
@@ -2141,6 +2145,28 @@ gtk_tree_view_get_real_requested_width_from_column (GtkTreeView       *tree_view
   return real_requested_width;
 }
 
+static gint
+gtk_tree_view_get_real_natural_width_from_column (GtkTreeView       *tree_view,
+                                                  GtkTreeViewColumn *column)
+{
+  GtkTreeViewColumnPrivate *column_priv;
+  GtkRequisition button_natural_size;
+  gint column_natural_width;
+
+  column_priv = GTK_TREE_VIEW_COLUMN_GET_PRIVATE (column);
+  column_natural_width = column_priv->natural_width;
+
+  if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
+    {
+      gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (column->button),
+                                            NULL, &button_natural_size);
+
+      column_natural_width = MAX (column_natural_width, button_natural_size.width);
+    }
+
+  return column_natural_width;
+}
+
 /* GtkWidget::size_allocate helper */
 static void
 gtk_tree_view_size_allocate_columns (GtkWidget *widget,
@@ -2150,9 +2176,10 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
   GList *list, *first_column, *last_column;
   GtkTreeViewColumn *column;
   GtkAllocation allocation;
-  gint width = 0;
+  gint width = 0, natural_width;
   gint extra, extra_per_column, extra_for_last;
   gint full_requested_width = 0;
+  gint full_natural_width = 0;
   gint number_of_expand_columns = 0;
   gboolean column_changed = FALSE;
   gboolean rtl;
@@ -2186,6 +2213,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
        continue;
 
       full_requested_width += gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
+      full_natural_width += gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
 
       if (column->expand)
        number_of_expand_columns++;
@@ -2210,7 +2238,9 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
     }
   else
     {
+      full_natural_width -= full_requested_width;
       extra = MAX (widget->allocation.width - full_requested_width, 0);
+      natural_width = MIN (extra, full_natural_width);
       extra_for_last = 0;
 
       tree_view->priv->last_extra_space = extra;
@@ -2232,6 +2262,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
        list = (rtl ? list->prev : list->next)) 
     {
       gint real_requested_width = 0;
+      gint real_natural_width = 0;
       gint old_width;
 
       column = list->data;
@@ -2257,10 +2288,14 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget,
        }
 
       real_requested_width = gtk_tree_view_get_real_requested_width_from_column (tree_view, column);
+      real_natural_width = gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
+      real_natural_width -= real_requested_width;
 
       allocation.x = width;
       column->width = real_requested_width;
 
+      if (full_natural_width > 0)
+        column->width += natural_width * real_natural_width / full_natural_width;
       if (column->expand)
        {
          if (number_of_expand_columns == 1)
@@ -5656,10 +5691,13 @@ validate_row (GtkTreeView *tree_view,
 
   for (list = tree_view->priv->columns; list; list = list->next)
     {
-      gint tmp_width;
-      gint tmp_height;
+      GtkTreeViewColumnPrivate *column_priv;
+      GtkRequisition requested_size;
+      GtkRequisition natural_size;
+      gint padding;
 
       column = list->data;
+      column_priv = GTK_TREE_VIEW_COLUMN_GET_PRIVATE (column);
 
       if (! column->visible)
        continue;
@@ -5672,12 +5710,15 @@ validate_row (GtkTreeView *tree_view,
                                               node->children?TRUE:FALSE);
       gtk_tree_view_column_cell_get_size (column,
                                          NULL, NULL, NULL,
-                                         &tmp_width, &tmp_height);
+                                         &requested_size.width,
+                                          &requested_size.height);
+      gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (column),
+                                            NULL, &natural_size);
 
       if (!is_separator)
        {
-          tmp_height += vertical_separator;
-         height = MAX (height, tmp_height);
+          requested_size.height += vertical_separator;
+         height = MAX (height, requested_size.height);
          height = MAX (height, tree_view->priv->expander_size);
        }
       else
@@ -5690,26 +5731,31 @@ validate_row (GtkTreeView *tree_view,
 
       if (gtk_tree_view_is_expander_column (tree_view, column))
         {
-         tmp_width = tmp_width + horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
+         padding = horizontal_separator + (depth - 1) * tree_view->priv->level_indentation;
 
          if (TREE_VIEW_DRAW_EXPANDERS (tree_view))
-           tmp_width += depth * tree_view->priv->expander_size;
+           padding += depth * tree_view->priv->expander_size;
        }
       else
-       tmp_width = tmp_width + horizontal_separator;
+       padding = horizontal_separator;
 
       if (draw_vgrid_lines)
         {
          if (list->data == first_column || list->data == last_column)
-           tmp_width += grid_line_width / 2.0;
+           padding += grid_line_width / 2.0;
          else
-           tmp_width += grid_line_width;
+           padding += grid_line_width;
        }
 
-      if (tmp_width > column->requested_width)
+      requested_size.width += padding;
+      natural_size.width += padding;
+
+      if (requested_size.width > column->requested_width ||
+          natural_size.width > column_priv->natural_width)
        {
          retval = TRUE;
-         column->requested_width = tmp_width;
+         column->requested_width = requested_size.width;
+         column_priv->natural_width = natural_size.width;
        }
     }
 
@@ -15636,5 +15682,46 @@ gtk_tree_view_get_tooltip_column (GtkTreeView *tree_view)
   return tree_view->priv->tooltip_column;
 }
 
+static void
+gtk_tree_view_extended_layout_get_desired_size (GtkExtendedLayout *layout,
+                                                GtkRequisition    *minimal_size,
+                                                GtkRequisition    *desired_size)
+{
+  GtkTreeView *tree_view;
+  gint natural_width = 0;
+  GList *column_iter;
+  GtkRequisition requisition;
+
+  tree_view = GTK_TREE_VIEW (layout);
+
+  gtk_widget_size_request (GTK_WIDGET (layout), &requisition);
+
+  for (column_iter = tree_view->priv->columns; column_iter; column_iter = column_iter->next)
+    {
+      GtkTreeViewColumn *column = column_iter->data;
+
+      if (!column->visible)
+        continue;
+
+      natural_width += gtk_tree_view_get_real_natural_width_from_column (tree_view, column);
+    }
+
+  if (minimal_size)
+    *minimal_size = requisition;
+
+  if (desired_size)
+    {
+      desired_size->height = requisition.height;
+      desired_size->width = natural_width;
+    }
+}
+
+static void
+gtk_tree_view_extended_layout_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_desired_size = gtk_tree_view_extended_layout_get_desired_size;
+}
+
+
 #define __GTK_TREE_VIEW_C__
 #include "gtkaliasdef.c"
index edec5deffedde0d5540deeb79de1811636d073cf..0a1dd5136440ba674515e4c6a66f6ed8934c7b53 100644 (file)
@@ -26,6 +26,7 @@
 #include "gtkbutton.h"
 #include "gtkalignment.h"
 #include "gtklabel.h"
+#include "gtkextendedlayout.h"
 #include "gtkhbox.h"
 #include "gtkmarshalers.h"
 #include "gtkarrow.h"
@@ -155,13 +156,18 @@ static void gtk_tree_view_column_clear_attributes_by_info      (GtkTreeViewColum
 /* GtkBuildable implementation */
 static void gtk_tree_view_column_buildable_init                 (GtkBuildableIface     *iface);
 
+static void gtk_tree_view_column_extended_layout_init          (GtkExtendedLayoutIface *iface);
+
 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
                                                gtk_tree_view_column_cell_layout_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
-                                               gtk_tree_view_column_buildable_init))
+                                               gtk_tree_view_column_buildable_init)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
+                                                gtk_tree_view_column_extended_layout_init))
+
 
 
 static void
@@ -344,6 +350,8 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
                                                      G_MAXINT,
                                                      -1,
                                                      GTK_PARAM_READWRITE));
+
+  g_type_class_add_private (class, sizeof (GtkTreeViewColumnPrivate));
 }
 
 static void
@@ -2608,12 +2616,12 @@ gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
  * primarily by the #GtkTreeView.
  **/
 void
-gtk_tree_view_column_cell_get_size (GtkTreeViewColumn  *tree_column,
+gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn  *tree_column,
                                    const GdkRectangle *cell_area,
                                    gint               *x_offset,
                                    gint               *y_offset,
-                                   gint               *width,
-                                   gint               *height)
+                                    GtkRequisition     *minimal_size,
+                                    GtkRequisition     *desired_size)
 {
   GList *list;
   gboolean first_cell = TRUE;
@@ -2621,10 +2629,10 @@ gtk_tree_view_column_cell_get_size (GtkTreeViewColumn  *tree_column,
 
   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
 
-  if (height)
-    * height = 0;
-  if (width)
-    * width = 0;
+  minimal_size->height = 0;
+  minimal_size->width = 0;
+  desired_size->height = 0;
+  desired_size->width = 0;
 
   gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
   
@@ -2632,33 +2640,59 @@ gtk_tree_view_column_cell_get_size (GtkTreeViewColumn  *tree_column,
     {
       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
       gboolean visible;
-      gint new_height = 0;
-      gint new_width = 0;
+      GtkRequisition min_req, nat_req;
+
       g_object_get (info->cell, "visible", &visible, NULL);
 
       if (visible == FALSE)
        continue;
 
-      if (first_cell == FALSE && width)
-       *width += tree_column->spacing;
+      if (first_cell == FALSE)
+        {
+         min_req.width += tree_column->spacing;
+         nat_req.width += tree_column->spacing;
+        }
+
+      gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (info->cell),
+                                            &min_req, &nat_req);
 
-      gtk_cell_renderer_get_size (info->cell,
-                                 tree_column->tree_view,
-                                 cell_area,
-                                 x_offset,
-                                 y_offset,
-                                 &new_width,
-                                 &new_height);
+      min_req.width += focus_line_width * 2;
+      min_req.height += focus_line_width * 2;
+      nat_req.width += focus_line_width * 2;
+      nat_req.height += focus_line_width * 2;
+
+      info->requested_width = MAX (info->requested_width, min_req.width);
 
-      if (height)
-       * height = MAX (*height, new_height + focus_line_width * 2);
-      info->requested_width = MAX (info->requested_width, new_width + focus_line_width * 2);
-      if (width)
-       * width += info->requested_width;
       first_cell = FALSE;
+
+      if (minimal_size)
+        *minimal_size = min_req;
+
+      if (desired_size)
+        *desired_size = nat_req;
     }
 }
 
+void
+gtk_tree_view_column_cell_get_size (GtkTreeViewColumn  *tree_column,
+                                   const GdkRectangle *cell_area,
+                                   gint               *x_offset,
+                                   gint               *y_offset,
+                                    gint               *width,
+                                    gint               *height)
+{
+  GtkRequisition min_req;
+
+  gtk_tree_view_column_cell_get_real_size (tree_column, cell_area,
+                                           x_offset, y_offset, &min_req, NULL);
+
+  if (width)
+    *width = min_req.width;
+
+  if (height)
+    *height = min_req.height;
+}
+
 /* rendering, event handling and rendering focus are somewhat complicated, and
  * quite a bit of code.  Rather than duplicate them, we put them together to
  * keep the code in one place.
@@ -3784,5 +3818,22 @@ gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
   return tree_column->tree_view;
 }
 
+static void
+gtk_tree_view_column_extended_layout_get_desired_size (GtkExtendedLayout *layout,
+                                                       GtkRequisition    *minimal_size,
+                                                       GtkRequisition    *desired_size)
+{
+  gtk_tree_view_column_cell_get_real_size (GTK_TREE_VIEW_COLUMN (layout),
+                                           NULL, NULL, NULL,
+                                           minimal_size, desired_size);
+}
+
+static void
+gtk_tree_view_column_extended_layout_init (GtkExtendedLayoutIface *iface)
+{
+  iface->get_desired_size = gtk_tree_view_column_extended_layout_get_desired_size;
+}
+
+
 #define __GTK_TREE_VIEW_COLUMN_C__
 #include "gtkaliasdef.c"
index b06e845d9fe9c115693fb36bc82c9fd08de60911..75b4c5afc2a95850b6d04b72e899c84ff6344e39 100644 (file)
@@ -51,6 +51,7 @@ typedef enum
 
 typedef struct _GtkTreeViewColumn      GtkTreeViewColumn;
 typedef struct _GtkTreeViewColumnClass GtkTreeViewColumnClass;
+typedef struct _GtkTreeViewColumnPrivate GtkTreeViewColumnPrivate;
 
 typedef void (* GtkTreeCellDataFunc) (GtkTreeViewColumn *tree_column,
                                      GtkCellRenderer   *cell,